package org.ns.framework.webmvc.error;

import java.util.HashMap;
import java.util.Map;

import org.ns.framework.webmvc.ResponseEntityBuild;
import org.ns.framework.webmvc.ResponseErrorStatus;
import org.ns.framework.webmvc.ResponseStatus.ErrorStatus;

public class ApiException extends RuntimeException {

	private static final long serialVersionUID = 1L;

	private int httpStatus = 200;

	private Integer status; // 错误状态 -- 数字状态
	
    private String state; // 错误状态 -- 文字状态

    private Object content; // 应答内容

    private String message; // 应答消息

    private String localeMessage; // 应答消息
    
    private String errplace; // 错误位置

    private Object[] messageArgs;
    
    public ApiException(ResponseErrorStatus status, String message) {
        this(status);
        this.message = message;
        initLocaleMessage(message);
    }

    public ApiException(ResponseErrorStatus status, String message, String errplace) {
        this(status);
        this.errplace = errplace;
        this.message = message;
        initLocaleMessage(message);
    }

    public ApiException(ResponseErrorStatus status) {
        super(status.getMessage());
        this.httpStatus = status.getHttpStatus();
        this.state = status.getState();
        this.message = status.getMessage();
        this.status = status.getStatus();
        this.localeMessage = status.getLocaleMessage();
    }

    public ApiException(int httpStatus, ErrorStatus errorStatus, Object content, String message, String errplace) {
        super(message);
        this.httpStatus = httpStatus;
        this.state = errorStatus.getState();
        this.status = errorStatus.getStatus();
        this.content = content;
        this.message = message;
        this.errplace = errplace;
        initLocaleMessage(message);
    }

    public ApiException(int httpStatus, ErrorStatus errorStatus, String message) {
        super(message);
        this.httpStatus = httpStatus;
        this.state = errorStatus.getState();
        this.status = errorStatus.getStatus();
        this.message = message;
        initLocaleMessage(message);
    }

    public ApiException(int httpStatus, ErrorStatus errorStatus, Object content, String message) {
        super(message);
        this.httpStatus = httpStatus;
        this.state = errorStatus.getState();
        this.status = errorStatus.getStatus();
        this.content = content;
        this.message = message;
        initLocaleMessage(message);
    }

    private void initLocaleMessage(String message) {
    	if (message != null && !message.isEmpty() && message.startsWith("locale:")) {
    		int index = message.indexOf("=");
    		if (index == -1) {
    			localeMessage = message.substring(7);
    			message = null;
    		} else {
    			localeMessage = message.substring(7, index);
    			this.message = message.substring(index + 1);
    		}
    	} else if (localeMessage == null) {
    		if (state != null && !state.isEmpty()) {
    			localeMessage = state;
    		} else if (status != null) {
    			localeMessage = "status." + status;
    		}
    	}
    }
    
    public ApiException setLocaleMessage(String localeMessage) {
		this.localeMessage = localeMessage;
		return this;
	}
    
    public ApiException setMessageArgs(Object... messageArgs) {
		this.messageArgs = messageArgs;
		return this;
	}
    
    public ApiException setContent(Object content) {
		this.content = content;
		return this;
	}
    public ApiException setContentMap(Object... keyvals) {
    	Map<String, Object> map = new HashMap<>();
    	int size = keyvals.length/2;
    	for (int i = 0; i < size; i+=2) {
    		if (keyvals[i] != null) {
				String key = String.valueOf(keyvals[i]);
				Object value = keyvals[i + 1];
				map.put(key, value);
    		}
		}
    	this.content = map;
    	return this;
    }
    
    public ApiException setErrplace(String errplace) {
		this.errplace = errplace;
		return this;
	}
    
    public ApiException setMessage(String message) {
		this.message = message;
		initLocaleMessage(message);
		return this;
	}
    
    @Override
    public synchronized Throwable fillInStackTrace() {
        return null;
    }
    
    public void assertThrowEx(boolean condition) {
    	if (condition) {
    		throw this;
    	}
    }

    public ResponseEntityBuild create() {
        return ResponseEntityBuild.create()
                .setHttpStatus(httpStatus)
                .setStatus(status)
                .setState(state)
                .setMessage(message)
                .setLocaleMessage(localeMessage)
                .setMessageArgs(messageArgs)
                .setContent(content)
                .setErrplace(errplace);
    }
    
    public String getState() {
		return state;
	}
}
